package ezxpns.gui.tab;

import java.awt.*;
import java.io.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import ezxpns.*;
import ezxpns.types.*;
import ezxpns.util.*;

@SuppressWarnings("serial")
public class TabGUIDefault extends TabGUI implements Undoable<Manager.View>
{
	private File file;
	private boolean saved;
	private Undoable<Manager.View> manager;
	private JTextArea editor;
	private int start,start2;
	private int end,end2;
	public TabGUIDefault()
	{
		setLayout(new BorderLayout());
		editor=new JTextArea();
		JScrollPane scroll=new JScrollPane(editor);
		add(scroll,BorderLayout.CENTER);
		editor.getDocument().addUndoableEditListener
		(
			new UndoableEditListener()
			{
				public void undoableEditHappened(UndoableEditEvent event)
				{
					CommandGroup edit=new CommandGroup();
					edit.add(new Command<Bound<VLong>>("text select",new Bound<VLong>(new VLong(start2),new VLong(end2))));
					edit.add(new Command<Pointer<UndoableEditEvent>>("text edit",new Pointer<UndoableEditEvent>(event)));
					manager.exec(edit);
					saved=false;
				}
			}
		);
		editor.addCaretListener
		(
			new CaretListener()
			{
				public void caretUpdate(CaretEvent caret)
				{
					start2=start;
					end2=end;
					start=caret.getMark();
					end=caret.getDot();
				}
			}
		);
		editor.setTabSize(4);
	}
	private void init()
	{
		editor.setText(manager.getView().getText());
		editor.select(0,0);
		editor.requestFocusInWindow();
		saved=true;
	}
	public void fileNew()
	{
		try
		{
			manager=new UndoWrapper<Manager,Manager.View>(new Manager(null));
			file=null;
			init();
		}
		catch(Exception e)
		{
			e.printStackTrace();
		}
	}
	public boolean fileOpen(File file2)
	{
		if( file2==null ) return false;
		FileInputStream fin;
		try
		{
			fin=new FileInputStream(file2);
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog
			(
				(Frame)this.getTopLevelAncestor(),
				"Could not open \""+file2.getName()+"\"!",
				"File Open",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}
		try
		{
			manager=new UndoWrapper<Manager,Manager.View>(new Manager(fin));
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog
			(
				(Frame)this.getTopLevelAncestor(),
				"\""+file2.getName()+"\" has an unrecognized format!",
				"File Open",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}
		file=new File(file2.getPath());
		init();
		return true;
	}
	public boolean fileSave(File file2)
	{
		if( file2==null ) return false;
		OutputStream fout;
		try
		{
			fout=new FileOutputStream(file2);
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog
			(
				(Frame)this.getTopLevelAncestor(),
				"Could not save to \""+file2.getName()+"\"!",
				"File Save",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}
		manager.exec(new CommandGroup(new Command<VString>("text set",new VString(editor.getText()))));
		try
		{
			manager.getView().export(fout);
		}
		catch(Exception e)
		{
			JOptionPane.showMessageDialog
			(
				(Frame)this.getTopLevelAncestor(),
				"Error in saving to \""+file2.getName()+"\"!",
				"File Save",
				JOptionPane.ERROR_MESSAGE
			);
			return false;
		}
		file=new File(file2.getPath());
		saved=true;
		return true;
	}
	public void fileClose()
	{
	}
	public File getFile()
	{
		if( file==null ) return null;
		return new File(file.getPath());
	}
	public boolean getSaved()
	{
		return saved;
	}
	public void exec(CommandGroup cmdGroup)
	{
		manager.exec(cmdGroup);
	}
	public void undo()
	{
		manager.undo();
		Bound<VLong> selection=manager.getView().getSelection();
		Caret caret=editor.getCaret();
		caret.setDot((int)selection.lower().value());
		caret.moveDot((int)selection.upper().value());
	}
	public void redo()
	{
		manager.redo();
	}
	public void hop()
	{
		manager.hop();
	}
	public boolean canUndo()
	{
		if( manager==null ) return false;
		return manager.canUndo();
	}
	public boolean canRedo()
	{
		if( manager==null ) return false;
		return manager.canRedo();
	}
	public boolean canHop()
	{
		if( manager==null ) return false;
		return manager.canHop();
	}
	public Manager.View getView()
	{
		return manager.getView();
	}
}
